﻿

using IotContract.Dtos.Servers;
using IotContract.Dtos.Servers.Process;
using IotContract.Models.Clients;
using IotServerService.Entities;
using Mapster;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using XT.Common.Extensions;
using XT.Sql;

namespace IotServerService.Services;
/// <summary>
/// Db数据访问
/// </summary>
public class DbService
{
    private readonly XTDbContext _context;
    public DbService(XTDbContext context)
    {
        _context = context;
    }
    /// <summary>
    /// 添加程序
    /// </summary>
    /// <param name="command"></param>
    /// <returns></returns>
    public async Task<ProgramInfo> AddProgram(ClientConnectCommand command)
    {
        var db = _context.GetEntityDb<ProgramInfo>();
        var program = await db.AsQueryable().Where(x => x.RunPath == command.RunPath).SingleAsync();
        if (program == null)
        {
            string name = Guid.NewGuid().ToString();


            var id = await db.InsertReturnSnowflakeIdAsync(new ProgramInfo
            {

                Name = name,
                ProgramType = command.ProgramType,
                RunPath = command.RunPath,
                IPAddress = command.IPAddress,
                Runtime = DateTime.Now
            });
            return new ProgramInfo
            {
                Id = id,
                Name = name
            };



        }
        else
        {
            // 更新启动时间
            await db.AsUpdateable().SetColumns(x => x.Runtime == DateTime.Now).SetColumns(x => x.IPAddress == command.IPAddress).Where(x => x.Id == program.Id).ExecuteCommandAsync();
            return program;
        }

    }
    /// <summary>
    /// 添加程序状态
    /// </summary>
    /// <param name="command"></param>
    /// <returns></returns>
    public async Task<ProgramStatus> AddProgramStatus(ClientStatusCommand command)
    {
        var db = _context.GetEntityDb<ProgramStatus>();
        var status = await db.AsQueryable().Where(x => x.ProgramId == command.ProgramId).SingleAsync();
        if (status == null)
        {
            // 插入后默认启用
            var id = await db.InsertReturnSnowflakeIdAsync(new ProgramStatus
            {
                StatusDes = command.StatusDes,
                ProgramId = command.ProgramId,
                Cpu = command.Cpu,
                Ram = command.Ram,
                Status = (int)command.Status,
                IsEnable = 1,
                Remark = command.Remark
            });
            return new ProgramStatus { Id = id, IsEnable = 1 };
        }
        else
        {
            // 更新数据
            status.Status = (int)command.Status;
            status.Cpu = command.Cpu;
            status.Ram = command.Ram;
            status.StatusDes = command.StatusDes;
            status.Remark = command.Remark;
            await db.UpdateAsync(status);
            return status;
        }
    }

    /// <summary>
    /// 根据设备id获取程序id
    /// </summary>
    /// <param name="equipId"></param>
    /// <returns></returns>
    public async Task<long> GetProgramId(long equipId)
    {
        var rep = _context.GetEntityDb<EquipInfo>();
        var id = await rep.AsQueryable().Where(x => x.Id == equipId).Select(x => x.ProgramId).SingleAsync();
        return id;
    }
    /// <summary>
    /// 获取设备信息
    /// </summary>
    /// <param name="command"></param>
    /// <returns></returns>
    public async Task<List<IotEquipDto>> GetEquips(ClientRequestCommand command)
    {

        List<IotEquipDto> equips = new List<IotEquipDto>();
        // 通过RequestType进行容错，保护数据
        if (command.RequestType != "1" || command.ProgramId == 0)
        {
            return equips;
        }
        var rep = _context.GetEntityDb<EquipInfo>();
        if (command.EquipId > 0)
        {
            var data = await rep.AsQueryable().LeftJoin<ProgramInfo>((x, y) => x.ProgramId == y.Id).Where(x => x.Id == command.EquipId && x.IsDelete==false && x.IsEnable==1).Select((x, y) => new IotEquipDto
            {
                Id=x.Id,
                ProgramId=y.Id,
                ProgramType=y.ProgramType
            },true).SingleAsync();                               

            if (data == null) return equips;
            equips.Add(data.Adapt<IotEquipDto>());
            return equips;

        }
        else
        {
            var datas = await rep.AsQueryable().LeftJoin<ProgramInfo>((x,y)=>x.ProgramId==y.Id).Where(x => x.ProgramId == command.ProgramId && x.IsDelete == false && x.IsEnable==1).Select((x, y) => new IotEquipDto
            {
                Id = x.Id,
                ProgramId = y.Id,
                ProgramType = y.ProgramType
            }, true).ToListAsync();
            equips.AddRange(datas.Adapt<List<IotEquipDto>>());

            return equips;
        }   

    }
    /// <summary>
    /// 根据设备编码获取设备信息
    /// </summary>
    /// <param name="equipNum"></param>
    /// <param name="protobufType"></param>
    /// <returns></returns>
    public async Task<IotEquipDto> GetEquip(string equipNum,string protobufType="")
    {
        var rep = _context.GetEntityDb<EquipInfo>();
        var equip=await rep.AsQueryable().WhereIF(protobufType.IsNotNullOrEmpty(),x=>x.ProtobufType == protobufType).Where(x=>x.Num==equipNum).
            Select(x=>new IotEquipDto
            {
                ProtobufType=x.ProtobufType,
                Id=x.Id,
                ProgramId=x.ProgramId
               
            }).FirstAsync();
        return equip;

    }
    /// <summary>
    /// 获取设备点位
    /// </summary>
    /// <param name="command"></param>
    /// <returns></returns>
    public async Task<List<EquipTagDto>> GetEquipTags(ClientRequestCommand command)
    {
        List<EquipTagDto> tags = new List<EquipTagDto>();
        // 不包含程序id，强制退出
        if ( command.ProgramId == 0)
        {
            return tags;
        }
        var rep = _context.GetEntityDb<EquipTag>();
        var datas=await rep.AsQueryable().InnerJoin<EquipInfo>((x,y)=>x.EquipInfoId==y.Id).WhereIF(command.EquipId>0,(x,y)=>x.EquipInfoId==command.EquipId).Where((x,y)=>x.IsEnable==1 && y.ProgramId==command.ProgramId && x.IsDelete==false).ToListAsync();

        tags.AddRange(datas.Adapt<List<EquipTagDto>>());

        return tags;
    }

    /// <summary>
    /// 获取设备点位
    /// </summary>
    /// <param name="command"></param>
    /// <returns></returns>
    public async Task<List<EquipTagDto>> GetAllEquipTags()
    {
        List<EquipTagDto> tags = new List<EquipTagDto>();

        var rep = _context.GetEntityDb<EquipTag>();
        var datas = await rep.AsQueryable().Where(z => z.Id != null).ToListAsync();

        tags.AddRange(datas.Adapt<List<EquipTagDto>>());

        return tags;
    }

    #region 定制化
    /// <summary>
    /// 获取入库站台组
    /// </summary>
    /// <returns></returns>
    public async Task<List<EnterTagGroupDto>> GetEnterTags()
    {
       
            var datas = await _context.Db.Ado.SqlQueryAsync<EnterTagGroupDto>(@"

SELECT P.BIND_NUM AS tagNumber1, '0' AS tagNumber2
FROM TH_STACKER_PORT_REF P
INNER JOIN TH_STACKER A ON P.STACKER_ID = A.ID
WHERE P.IS_ENTRANCE = 1
AND P.IS_DEL = 0
AND A.IS_DEL = 0
AND A.STACKER_CODE NOT IN (
    SELECT S.STACKER_CODE
    FROM TH_STACKER S
    INNER JOIN TH_STACKER_PORT_REF P1 ON P1.STACKER_ID = S.ID
    INNER JOIN TH_STACKER_PORT_REF P2 ON P2.STACKER_ID = S.ID
    WHERE P1.IS_ENTRANCE = 1
    AND P2.STACKER_ID = P1.STACKER_ID
    AND P2.FLOOR_NUM = P1.FLOOR_NUM
    AND P2.BIND_NUM <> P1.BIND_NUM
    AND P2.IS_ENTRANCE = 1
    AND P1.IS_DEL = 0
    AND S.IS_DEL = 0
    AND P1.FORK_NUM = 1
)

UNION 

SELECT   P1.BIND_NUM AS tagNumber1, P2.BIND_NUM AS tagNumber2
FROM TH_STACKER S
inner JOIN TH_STACKER_PORT_REF P1 ON P1.STACKER_ID = S.ID
inner JOIN TH_STACKER_PORT_REF P2 ON P2.STACKER_ID = S.ID
WHERE P1.IS_ENTRANCE = 1
AND P2.STACKER_ID = P1.STACKER_ID
AND P2.FLOOR_NUM = P1.FLOOR_NUM
AND P2.BIND_NUM <> P1.BIND_NUM
AND P2.IS_ENTRANCE = 1
AND P1.IS_DEL = 0
AND S.IS_DEL = 0
AND P1.FORK_NUM = 1


");
            return datas;
      
    }
    #endregion


}
